
#ifndef _TTG_EXTRAS_SERIALIZATION_BYTESERIALIZER_
#define _TTG_EXTRAS_SERIALIZATION_BYTESERIALIZER_
#include "Common/Definitions.h"

#include <vector>
#include "Serializer.h"
#include "ByteDeSerializer.h"

namespace ttg_internal
{
	namespace extras
	{
		namespace serialization
		{
			enum ByteTags
			{
				NotSafeSerialization = 0xF0,
				SafeSerialization = 0xF1,
				ReferenceEnd = 0xF3,
				NullReferenceFlag = 0xF4,
				NotNullReferenceFlag = 0xF5
			};
		}
	}
}

namespace ttg
{
	namespace extras
	{
		namespace serialization
		{
			//Serializes data into byte stream.
			//
			//Safe serialization format:
			//<Goal> := 0xF1{<Serialized value>}
			//<Serialized value> := <Hash value><Serialized data>
			//<Serialized data> := <Raw data> | {<Serialized value>}<Reference end>
			//
			//Not-safe serialization format:
			//<Goal> := 0xF0{<Serialized value>}
			//<Serialized value> := <Raw data> | <Reference flag>[<Serialized value>]
			//
			//Where:
			//	Hash value - 30 bits with hash of variable name+size and 2 bits with flag
			//				(2 for NULL reference, 1 for not-NULL reference, 0 for flat data).
			//	Size - 4 bytes with size of serialized data.
			//	Raw data - just a raw data.
			//	Reference end - 1 byte with 0xF2 value.
			//  Reference flag - 1 byte with 0xF3 for NULL reference and 0xF4 for not NULL reference.
			class ByteSerializer :public Serializer
			{
				private:
					static const size_t DEFAULT_SIZE = 16 * 1024;
					static const size_t DEFAULT_INC = 4 * 1024;
					std::vector<unsigned char> data;
					bool is_safe;
				private:
					//Prepares data for adding new object with given size.
					void prepareData(size_t inc_size);
					//Writes hash to the byte stream.
					void writeHash(unsigned __int32 hash);
				protected:
					//Serializer member.
					virtual void serializeMemory(const void *data, size_t size, const char *name);
					//Serializer member.
					virtual void serializeReferenceStart(bool is_null, const char *name);
					//Serializer member.
					virtual void serializeReferenceEnd();
				public:
					//Serializer member.
					virtual DeSerializer *createDeSerializer()
					{ return new ByteDeSerializer(this->getData(), this->getSize()); }
					//Creates empty serialyzer.
					ByteSerializer(bool is_safe);
					//Returns size of serialized data (in bytes).
					inline size_t getSize()
					{ return data.size(); }
					//Returns pointer to serialized data.
					inline unsigned char *getData()
					{ return &data[0]; }
			};
		}
	}
}

#endif
